/*
 * [y] hybris Platform
 *
 * Copyright (c) 2000-2017 SAP SE
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of SAP
 * Hybris ("Confidential Information"). You shall not disclose such
 * Confidential Information and shall use it only in accordance with the
 * terms of the license agreement you entered into with SAP Hybris.
 */
package acc.asset.sync.task;

import de.hybris.deltadetection.ItemChangeDTO;
import de.hybris.platform.core.PK;
import de.hybris.platform.core.model.media.MediaModel;
import de.hybris.platform.servicelayer.media.MediaService;
import de.hybris.platform.servicelayer.model.ModelService;
import de.hybris.y2ysync.enums.Y2YSyncType;
import de.hybris.y2ysync.task.runner.TaskContext;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import org.springframework.util.SerializationUtils;


/**
 *
 */
public class DemoTaskContext extends TaskContext
{
	private final Map<String, Object> ctx;
	private final ModelService modelService;
	private final MediaService mediaService;

	public DemoTaskContext(final ModelService modelService, final MediaService mediaService, final Map<String, Object> ctx)
	{
		super(modelService, mediaService, ctx);
		this.ctx = Objects.requireNonNull(ctx, "ctx can't be null");
		this.modelService = Objects.requireNonNull(modelService, "modelService can't be null");
		this.mediaService = Objects.requireNonNull(mediaService, "mediaService can't be null");
	}

	@Override
	public String getSyncExecutionId()
	{
		return this.getRequiredValue(String.class, "syncExecutionID");
	}

	@Override
	public String getConditionToTrigger()
	{
		return this.getRequiredValue(String.class, "conditionName");
	}

	@Override
	public String getImpExHeader()
	{
		return this.getRequiredValue(String.class, "impexHeader");
	}

	@Override
	public String getDataHubColumns()
	{
		final Optional<String> value = this.getValue(String.class, "dataHubColumns");
		return value.isPresent() ? value.get() : "";
	}

	@Override
	public String getTypeCode()
	{
		return this.getRequiredValue(String.class, "typeCode");
	}

	@Override
	public List<ItemChangeDTO> getChanges()
	{
		if (this.getMediaPK() == null)
		{
			return Collections.EMPTY_LIST;
		}
		else
		{
			final MediaModel media = (MediaModel) this.modelService.get(this.getMediaPK());
			final byte[] data = this.mediaService.getDataFromMedia(media);
			return (List) SerializationUtils.deserialize(data);
		}

	}

	@Override
	public PK getMediaPK()
	{
		return this.getOptionalValue(PK.class, "mediaPK");
	}

	@Override
	public Y2YSyncType getSyncType()
	{
		return this.getRequiredValue(Y2YSyncType.class, "syncType");
	}

	@Override
	public String getDataHubType()
	{
		final Optional<String> value = this.getValue(String.class, "dataHubType");
		return value.orElse("");
	}

	private <T> T getRequiredValue(final Class<T> clazz, final String key)
	{
		final Optional<T> value = this.getValue(clazz, key);
		if (!value.isPresent())
		{
			throw new IllegalStateException("Context doesn't contain value for '" + key + "'");
		}
		return value.get();
	}

	private <T> T getOptionalValue(final Class<T> clazz, final String key)
	{
		final Optional<T> value = this.getValue(clazz, key);
		if (!value.isPresent())
		{
			return null;
		}
		else
		{
			return value.get();
		}
	}

	private <T> Optional<T> getValue(final Class<T> clazz, final String key)
	{
		Objects.requireNonNull(key, "key can't be null");
		final Object valueObj = this.ctx.get(key);
		if (valueObj == null)
		{
			return Optional.empty();
		}
		try
		{
			final T value = (T) valueObj;
			return Optional.of(value);
		}
		catch (final ClassCastException e)
		{
			throw new IllegalStateException("Couldn't cast " + valueObj + " to " + clazz, e);
		}
	}
}
